/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "ui3D视口.h"


#include "底层绘图/intern/Vulkan/Vulkan框架.h"


#include <thread>
#include <future>
#include <utility>
#include <time.h>





static float64 gdur;
static clock_t g时间start = clock();
static clock_t g时间end;



static uint16 g视口属性ID = 0;
static uint16 g视口变换ID = 0;
static uint16 g视口颜色ID = 0;
static uint16 g视口笔刷ID = 0;
static uint16 g视口元素ID = 0;
static uint16 g视口梯度ID = 0;


static S_结构对象指针 m_渲染Fence = nullptr;
static S_结构对象指针 m_渲染命令缓存 = nullptr;



static void f_3D视口纹理动画(C_Widget* self) {
	C_3D视口* view = dynamic_cast<C_3D视口*>(self);

	self->m_Size = vec_Max({ 2,2 }, self->m_Size);
	bool 大小改变 = f_surface_改变大小(view->m_Face, f_vec_UI(self->m_Size));
	if (大小改变 && !(view->m_正在渲染)) {
		//f_vg_set纹理(view->m_画布, 0, 0, view->m_Face->m_Color[view->m_Face->m_交换ID]);
		view->m_视口纹理绘制.f_绑定纹理(view->m_Face->m_Color[view->m_Face->m_交换ID], 0);
		view->m_正在渲染 = true;
	}
}


static void f_3D视口布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_3D视口* view = dynamic_cast<C_3D视口*>(self);

	view->m_正在渲染 = false;
	view->m_镜头->f_set宽高比(self->m_Size);

	
}


static void f_draw3D视口(C_Widget* self, S_2D画布* 画布) {
	C_3D视口* view = dynamic_cast<C_3D视口*>(self);

	view->m_框部件.m_属性 = f_vg_gen属性(画布);
	S_凸边图元 图元{};
	图元.属性 = f_vg_get属性(画布, view->m_框部件.m_属性);
	view->m_框部件.f_Draw(画布, 图元, E_笔刷类型::e_单色填充);

	//图元 = {};
	//图元.属性 = f_vg_get属性(画布, view->m_框部件.m_属性);
	//view->m_视口纹理绘制.f_Draw(画布, view->m_框部件.m_属性, );
	view->m_视口纹理绘制.f_Draw(画布, view->m_框部件.m_属性, E_笔刷类型::e_纹理, view->m_Face->m_Color[view->m_Face->m_交换ID]);
	
}

static void f_set3D视口部件变换(C_Widget* self) {
	C_3D视口* view = dynamic_cast<C_3D视口*>(self);

	view->m_框部件.f_alloc(1);
	view->m_框部件.f_set单色填充(0, { {}, self->m_Size,{1, 0} }, S_UI主题::uic_灰色, S_Widget预设图元::m_矩形);
	
	view->m_视口纹理绘制.f_set(0, { {}, self->m_Size,{1, 0} }, S_Widget预设图元::m_矩形, { 255,255,255,255 });
	//view->m_视口纹理绘制.f_绑定纹理(view->m_Face->m_Color[view->m_Face->m_交换ID], 0);
	//auto& ctx = *(((S_绘图配置*)view->m_Face->m_绘图配置->m_渲染设备)->m_临时设备环境_以后替换层绘图环境);
	//view->m_正在渲染 = false;
	if (view->m_Scene) {
		view->m_镜头->f_set宽高比(self->m_Size);
		f_3D视口纹理动画(self);
	}

	view->m_正在渲染 = true;
}

/*DWORD WINAPI f_3D视口渲染(LPVOID pParam) {
	C_3D视口* view = (C_3D视口*)pParam;
	//return 0;
	return 0;
}*/



C_3D视口::C_3D视口(S_UI创建环境& ctx, S_设备环境& Ctx3D) : C_Widget(&ctx), m_Scene(nullptr), mf_场景外部更新回调(nullptr) {
	m_Face = f_surface_Create(Ctx3D, { 124, 56 });
	m_Face->m_Smaple = ctx.m_Mat->m_采样器;

	f_tex_安装纹理采样器(m_Face->m_Color[0], ctx.m_Mat->m_采样器);
	f_tex_安装纹理采样器(m_Face->m_Color[1], ctx.m_Mat->m_采样器);
	f_tex_安装纹理采样器(m_Face->m_Color[2], ctx.m_Mat->m_采样器);


	mf_布局Fun = f_3D视口布局;
	mf_DrawFun = f_draw3D视口;
	mf_变换修改 = f_set3D视口部件变换;
	//mf_动画更新 = f_3D视口纹理动画;


	m_是否延展 = { true, true };

	_m_默认镜头 = f_创建摄像机(Ctx3D);
	_m_默认镜头->f_set旋转(-20,-20,0);
	m_镜头 = _m_默认镜头;

	m_正在渲染 = true;
	m_退出渲染 = false;
	m_部件以绘 = false;
	m_开启光追 = false;
	m_使用全局采样参数 = true;

	auto* 绘图环境 = f_vk_get绘图环境(Ctx3D);
	m_渲染Fence = (S_结构对象指针)f_vk创建Fence(绘图环境);
	m_渲染命令缓存 = (S_结构对象指针)f_vk创建命令缓存(绘图环境, 1);
}

C_3D视口::~C_3D视口() {
	m_退出渲染 = true;

	Sleep(500);
	m_线程.joinable();

	f_surface_Release(m_Face);

	f_ob_销毁摄像机(m_镜头);
}

void C_3D视口::f_渲染() {
	if (m_Scene) {
		if (!m_正在渲染 || S_光追后端::g_渲染状态) return;

		if (mf_场景外部更新回调) mf_场景外部更新回调(this);


		float32 比例 = 1;
		vec2 视口大小 = {};
		vec2 视口偏移 = {};
		if (_m_默认镜头 == m_镜头) {
			m_镜头->f_set宽高比(m_Size);
			视口大小 = m_Size;
		}
		else {
			//float32 大 = DEF_Max(m_Size.x, m_Size.y);
			//float32 小 = DEF_Min(m_Size.x, m_Size.y);

			比例 = float32(m_镜头->m_分辨率.y) / float32(m_镜头->m_分辨率.x);
			if (m_Size.y >= m_Size.x * 比例) {
				视口大小.x = m_Size.x;
				视口大小.y = 视口大小.x * 比例;
			}
			else {
				视口大小.y = m_Size.y;
				视口大小.x = 视口大小.y * (float32(m_镜头->m_分辨率.x) / float32(m_镜头->m_分辨率.y));
			}
			
			
			//小 *= 比例;
			if (m_Size.x > 视口大小.x) {
				视口偏移.x = (m_Size.x - 视口大小.x) * 0.5;
			}
			if (m_Size.y > 视口大小.y) {
				视口偏移.y = (m_Size.y - 视口大小.y) * 0.5;
			}
			
			//m_镜头->m_分辨率
			m_镜头->f_set宽高比(视口大小);
		}
		
		m_Scene->f_Update(m_镜头);

		
		
		if (m_开启光追) {
			if (m_Scene->m_光追后端->m_渲染) {
				if (m_使用全局采样参数) {
					m_Scene->m_光追后端->m_mapPtr_渲染帧数据->m_BouncesNum = m_Scene->m_光追后端->m_预览渲染参数.反弹次数;
					m_Scene->m_光追后端->m_mapPtr_渲染帧数据->m_SamplesNum = m_Scene->m_光追后端->m_预览渲染参数.光采样;

					m_Scene->m_光追后端->m_mapPtr_渲染帧数据->m_ViewOffset_X = 视口偏移.x;
					m_Scene->m_光追后端->m_mapPtr_渲染帧数据->m_ViewOffset_Y = 视口偏移.y;

					if (m_Scene->m_光追后端->m_mapPtr_渲染帧数据->m_Frame > m_Scene->m_光追后端->m_预览渲染参数.采样次数) return;
				}
				m_Scene->f_RayRender(m_镜头, { uint32(视口大小.x), uint32(视口大小.y) }, *m_Face->m_Color[m_Face->m_交换ID]);
			}
		}
		else {
			//return;
			f_Draw_Begin_帧缓存(m_Face->m_Ctx, m_Face->m_帧缓存, m_Face->m_交换ID);
			m_Scene->f_Render(m_镜头, 视口大小, 视口偏移);
			f_Draw_end_帧缓存(m_Face->m_Ctx);
		}
	}
}



S_摄像机* f_ui_get3D视口摄像机(C_Widget* self) {
	assert(dynamic_cast<C_3D视口*>(self));
	return ((C_3D视口*)self)->m_镜头;
}

void f_ui_set3D视口摄像机(C_Widget* self, S_摄像机* camera) {
	((C_3D视口*)self)->m_镜头 = camera;
	((C_3D视口*)self)->m_镜头->f_set宽高比(self->m_Size);
}

void f_ui_set3D视口默认摄像机(C_Widget* self) {
	((C_3D视口*)self)->m_镜头 = ((C_3D视口*)self)->_m_默认镜头;
	((C_3D视口*)self)->m_镜头->f_set宽高比(self->m_Size);
}

bool f_ui_set3D视口是否为默认摄像机(C_Widget* self) {
	if (((C_3D视口*)self)->m_镜头 == ((C_3D视口*)self)->_m_默认镜头) {
		return true;
	}
	return false;
}

















